package com.hontech.desktoppastacooker.ui.fragment

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.hontech.desktoppastacooker.R
import com.hontech.desktoppastacooker.codec.decodeUint16
import com.hontech.desktoppastacooker.conn.Proto
import com.hontech.desktoppastacooker.conn.SerialPortMod
import com.hontech.desktoppastacooker.conn.serial.ByteView
import com.hontech.desktoppastacooker.conn.serial.Uint8
import com.hontech.desktoppastacooker.device.Rfid
import com.hontech.desktoppastacooker.device.RfidEvent
import com.hontech.desktoppastacooker.ui.window.showProg
import com.hontech.desktoppastacooker.utils.*
import com.jaredrummler.materialspinner.MaterialSpinner
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

class RfidFragment : Fragment() {

    private lateinit var rfidScanDelegate: RfidScanDelegate

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_rfid, null)
        RfidDelegate(view)
        rfidScanDelegate = RfidScanDelegate(view)
        return view
    }

    override fun onStart() {
        super.onStart()
        eventBus.register(this)
    }

    override fun onStop() {
        super.onStop()
        eventBus.unregister(this)
    }

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    fun onRfidScan(env: RfidEvent) {
        rfidScanDelegate.update(env.rfid)
    }
}

private class Item(view: View) : RecyclerView.ViewHolder(view) {

    private val rssi = view.findViewById<TextView>(R.id.id_item_rfid_rssi)
    private val pc = view.findViewById<TextView>(R.id.id_item_rfid_pc)
    private val crc = view.findViewById<TextView>(R.id.id_item_rfid_crc)
    private val epc = view.findViewById<TextView>(R.id.id_item_rfid_epc)

    fun setUp(rfid: Rfid) {
        rssi.text = "rssi:${rfid.rssi}"
        pc.text = "pc:${rfid.pc.toHex4()}"
        crc.text = "crc:${rfid.crc.toHex4()}"
        epc.text = "epc:${rfid.epc}"
    }
}

private class RfidScanDelegate(view: View) : RecyclerView.Adapter<Item>() {

    private val tvCount = view.findViewById<TextView>(R.id.id_rfid_tv_count)
    private val btnClear = view.findViewById<Button>(R.id.id_rfid_btn_count_clear)
    private val rv = view.findViewById<RecyclerView>(R.id.id_rfid_rv_list)

    private var count = 0
    private val list = ArrayList<Rfid>()

    init {
        btnClear.setOnClickListener {
            count = 0
            updateCount()
            list.clear()
            notifyDataSetChanged()
        }
        rv.adapter = this
        rv.layoutManager = LinearLayoutManager(rv.context, LinearLayoutManager.VERTICAL, false)
    }

    private fun updateCount() {
        tvCount.text = "RFID扫描计数$count"
    }

    fun update(rfid: Rfid) {
        count ++
        updateCount()

        list.remove(rfid)
        list.add(rfid)
        notifyDataSetChanged()
    }

    override fun onBindViewHolder(holder: Item, position: Int) {
        holder.setUp(list[position])
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Item {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_rfid, parent, false)
        return Item(view)
    }

    override fun getItemCount(): Int {
        return list.size
    }
}

private suspend fun rfidRequest(cmd: Int, parameter: ByteView): ByteView {
    val ret = SerialPortMod.request(
        3000,
        Proto.REQ_RF_TRANSLATE,
        arrayOf(Uint8(cmd), parameter)
    )
    ret.assertErr()
    val ec = Uint8()
    val resCmd = Uint8()
    val resParameter = ByteView()

    ret.parse(arrayOf(ec, resCmd, resParameter))
    if (resCmd.value != cmd) {
        throw IllegalStateException("rfid 数据异常")
    }
    return resParameter
}

private class RfidDelegate(view: View) {

    private val btnHard = view.findViewById<Button>(R.id.id_rfid_btn_query_hard_version)
    private val btnSoft = view.findViewById<Button>(R.id.id_rfid_btn_query_soft_version)
    private val btnMe = view.findViewById<Button>(R.id.id_rfid_btn_query_me)
    private val btnGetPower = view.findViewById<Button>(R.id.id_rfid_btn_get_power)
    private val btnSetPower = view.findViewById<Button>(R.id.id_rfid_btn_set_power)
    private val etPower = view.findViewById<EditText>(R.id.id_rfid_et_power)
    private val spMixer = view.findViewById<MaterialSpinner>(R.id.id_rfid_sp_mixer_g)
    private val spIf = view.findViewById<MaterialSpinner>(R.id.id_rfid_sp_if_g)
    private val etThrd = view.findViewById<EditText>(R.id.id_rfid_et_thrd)
    private val btnArgSet = view.findViewById<Button>(R.id.id_rfid_btn_arg_set)
    private val btnArgGet = view.findViewById<Button>(R.id.id_rfid_btn_arg_get)

    companion object {

        private suspend fun queryVersion(info: Int): String {
            val ret = rfidRequest(3, ByteView(byteArrayOf(info.toByte())))
            return String(ret.data, ret.index + 1, ret.len - 1)
        }

        private val MIXER_LIST = listOf("0dB", "3dB", "6dB", "9dB", "12dB", "15dB", "16dB")
        private val IFG_LIST = listOf("12dB", "18dB", "21dB", "24dB", "27dB", "30dB", "36dB", "40dB")
    }

    init {

        spMixer.setItems(MIXER_LIST)
        spIf.setItems(IFG_LIST)

        btnArgGet.onClick {

            val dialog = showProg("获取解调器参数", "")

            try {
                val ret = rfidRequest(0xF1, ByteView())
                val mixer = ret.data[ret.index].toUint8()
                val ifG = ret.data[ret.index + 1].toUint8()
                val thrd = decodeUint16(ret.data, ret.index + 2)
                dialog.showSuccess("解调器参数", "混频器增益:${MIXER_LIST[mixer]}\r\n" +
                        "中频放大器增益:${IFG_LIST[ifG]}\r\n" +
                        "信号解调阈值:${thrd.toHex4()}")
            } catch (e: Exception) {
                e.printStackTrace()
                dialog.error(e)
            }

        }

        btnArgSet.onClick {

            val dialog = showProg("设置解调器参数", "")


            try {
                val mixer = spMixer.selectedIndex
                val ifG = spIf.selectedIndex
                val thrd = etThrd.text.toString().toInt(16)

                val ret = rfidRequest(0xF0, ByteView(byteArrayOf(
                    mixer.toByte(),
                    ifG.toByte(),
                    (thrd shr 8).toByte(),
                    thrd.toByte()
                )))

                val ec = ret.data[ret.index].toUint8()
                if (ec != 0) {
                    throw IllegalStateException("异常:${ec}")
                }
                dialog.success("设置成功")

            } catch (e: Exception) {
                e.printStackTrace()
                dialog.error(e)
            }

        }

        btnSetPower.onClick {

            val dialog = showProg("设置功率", "")

            try {
                val power = etPower.toInt() * 100
                val ret = rfidRequest(0xB6, ByteView(byteArrayOf(
                    (power shr 8).toByte(),
                    power.toByte()))
                )
                val ec = ret.data[ret.index].toUint8()
                if (ec != 0) {
                    throw IllegalStateException("异常:${ec}")
                }
                dialog.success("设置成功")
            } catch (e: Exception) {
                e.printStackTrace()
                dialog.error(e)
            }
        }

        btnGetPower.onClick {

            val dialog = showProg("查询功率", "")
            try {
                val ret = rfidRequest(0xB7, ByteView())
                val power = decodeUint16(ret.data, ret.index)
                dialog.showSuccess("功率", "${power/100}dB")
            } catch (e: Exception) {
                e.printStackTrace()
                dialog.error(e)
            }

        }

        btnHard.onClick {

            val dialog = showProg("查询硬件版本", "")
            try {
                val ret = queryVersion(0)
                dialog.showSuccess("硬件版本", ret)
            } catch (e: Exception) {
                e.printStackTrace()
                dialog.error(e)
            }

        }

        btnSoft.onClick {
            val dialog = showProg("查询软件版本", "")
            try {
                val ret = queryVersion(1)
                dialog.showSuccess("软件版本", ret)
            } catch (e: Exception) {
                e.printStackTrace()
                dialog.error(e)
            }
        }

        btnMe.onClick {

            val dialog = showProg("查询制造商", "")
            try {
                val ret = queryVersion(2)
                dialog.showSuccess("制造商", ret)
            } catch (e: Exception) {
                e.printStackTrace()
                dialog.error(e)
            }
        }


    }
}



